package com.etlmaster.executor.processors.File;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.vfs2.FileContent;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileType;

import com.etlmaster.executor.utils.DpVfsUtils;
import com.etlmaster.executor.utils.LogWriter;
import com.etlmaster.util.vfs.HdfsFileSystem;

/**
 * 文件扫描器
 * 
 * @author Wugf
 * @date 2016-03-08
 */
public class FileScaner {
	private String regex;
	private final int MAX_FILE = 50000;

	public String getRegex() {
		return regex;
	}

	public void setRegex(String regex) {
		this.regex = regex;
	}

	private String path;

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	private int intervalDay = 0;

	private boolean before=false;
	public int getIntervalDay() {
		return intervalDay;
	}

	public void setIntervalDay(int intervalDay) {
		this.intervalDay = intervalDay;
	}

	private Boolean isDepthwise;

	public Boolean getIsDepthwise() {
		return isDepthwise;
	}

	public void setIsDepthwise(Boolean isDepthwise) {
		this.isDepthwise = isDepthwise;
	}

	private Object children;

	public List<FileScanInfo> foundFiles = new ArrayList<FileScanInfo>();
	private FileObject dir;

	public void findFilesByRegex() throws FileSystemException, ParseException {
		LogWriter.addLog("INFO", "开始扫描路径：{}", path);
		dir = DpVfsUtils.getInstance().resolveFile(path);

		FileObject[] childrens = dir.getChildren();
		
		for (int i = 0; i < childrens.length; i++) {
			if (i > MAX_FILE) {
				break;
			}
			FileObject fo = childrens[i];

			boolean isoutdated=false;
			if (fo.getType() == FileType.FILE) {
				String fileName = fo.getName().toString();
				Pattern p = Pattern.compile(regex);
				Matcher m = p.matcher(fileName);
				if (m.find()) {
					if (intervalDay > 0&&isOutDatedfile(fo)) 
					{
						isoutdated=true;
					}

					if(before&&isoutdated)
						((ArrayList<FileObject>) children).add(fo);
					else if(!before&&!isoutdated)
						((ArrayList<FileObject>) children).add(fo);

				}
			} else if (fo.getType() == FileType.FOLDER && isDepthwise) {
				if (intervalDay > 0&&isOutDatedFolderName(fo.getName().getBaseName()
						.toString())) {
					isoutdated=true;
					
				} 
				if(before){
					this.path = fo.getName().toString();
					findFilesByRegex();
				}
				else if(!before&&!isoutdated){
					this.path = fo.getName().toString();
					findFilesByRegex();
				}
			} else {
				LogWriter.addLog("DEBUG", "不进行深度扫描");
			}
		}

	}

	public boolean scanAndCheckResult() {
		try {
			if (regex != null && regex.length() > 0) {
				children = new ArrayList<FileObject>();
				findFilesByRegex();
			} else {
				if (isDepthwise) {
					LogWriter.addLog("WARN",
							"配置深层扫面，但是没有配置正则表达式，不能扫描下级目录，只扫描当前目录");
				}
				LogWriter.addLog("INFO", "扫描路径{}", path);
				findAllFiles();
			}

			getFoundFileList();
			return true;
		} catch (Exception e) {
			LogWriter.addLog("ERROR", e.getMessage());
			return false;
		} finally {
			DpVfsUtils.getInstance().closeFileObject(dir);
		}
	}

	public void findAllFiles() throws FileSystemException {
		dir = DpVfsUtils.getInstance().resolveFile(path);
		children = dir.getChildren();
		getFoundFileList();
	}

	private boolean isOutDatedFolderName(String folderName)
			throws ParseException {
		Pattern p = Pattern.compile("20\\d{6}");
		Matcher m = p.matcher(folderName);
		boolean rtnflag=false;
		if (m.find()) {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
			Date date = new Date();
			Date folderDate = sdf.parse(folderName.substring(0, 8));
			Calendar ca = Calendar.getInstance();
			ca.setTime(folderDate);
			ca.add(Calendar.DATE, intervalDay);
			Calendar nowca = Calendar.getInstance();
			nowca.setTime(date);
			if (!ca.before(nowca)) {
				rtnflag= false;
			} else {
				rtnflag= true;
			}
		} else {
			rtnflag= false;
		}
		return rtnflag;

	}

	private boolean isOutDatedfile(FileObject file) throws ParseException, FileSystemException {

		long time=System.currentTimeMillis();
		FileContent content = file.getContent();

		if(file.getFileSystem() instanceof HdfsFileSystem)
		{

		}else{
			time=content.getLastModifiedTime();
		}
		Date fileDate = new Date(time);
		Date date = new Date();
		Calendar ca = Calendar.getInstance();
		ca.setTime(fileDate);
		ca.add(Calendar.DATE, intervalDay);
		Calendar nowca = Calendar.getInstance();
		nowca.setTime(date);
		if (!ca.before(nowca)) {
			return false;
		} else {
			return true;
		}

	}

	private void getFoundFileList() throws FileSystemException {
		if (children != null) {
			boolean isList = children instanceof List;
			List<FileObject> listFileChildren = null;
			FileObject[] arrayFileChildren = null;
			if (isList) {
				listFileChildren = (List<FileObject>) children;
			} else {
				arrayFileChildren = (FileObject[]) children;
			}
			for (int i = 0; i < (isList ? listFileChildren.size()
					: arrayFileChildren.length); i++) {
				FileObject file = isList ? listFileChildren.get(i)
						: arrayFileChildren[i];
				if (FileType.FILE == file.getType()) {
					long modifytime=System.currentTimeMillis();
					FileContent content = file.getContent();

					if(file.getFileSystem() instanceof HdfsFileSystem)
					{
					}else{
						modifytime=content.getLastModifiedTime();
					}
					FileScanInfo fileInfo = new FileScanInfo(file.getName()
							.getRootURI(), file.getName().getPath(), file
							.getName().getBaseName(), content.getSize(),
							modifytime);
					foundFiles.add(fileInfo);
				}
			}
		}
	}

	public boolean isBefore() {
		return before;
	}

	public void setBefore(boolean before) {
		this.before = before;
	}

}
